package com.info33.platform.system.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.info33.platform.common.exception.TransactionalException;
import com.info33.platform.common.mvc.vo.Result;
import com.info33.platform.system.dao.SysScheduleDao;
import com.info33.platform.system.dao.SysScheduleParticipateDao;
import com.info33.platform.system.dto.SysScheduleDTO;
import com.info33.platform.system.entity.SysSchedule;
import com.info33.platform.system.entity.SysScheduleParticipate;
import com.info33.platform.system.service.SysScheduleParticipateService;
import com.info33.platform.system.service.SysScheduleService;
import com.info33.platform.system.vo.SysScheduleVO;
import com.info33.platform.system.vo.SysUserVO;

/**
 * @author admin
 */
@Service
@Transactional(rollbackFor = {Exception.class, Error.class})
public class SysScheduleServiceImpl extends ServiceImpl<SysScheduleDao, SysSchedule> implements SysScheduleService {

    @Autowired
    private SysScheduleDao sysScheduleDao;
    
    @Autowired
    private SysScheduleParticipateService sysScheduleParticipateService;
    
    @Autowired
    private SysScheduleParticipateDao sysScheduleParticipateDao;

	@Override
	public Result<?> saveSchedule(SysScheduleDTO sysScheduleDTO, SysUserVO currentUser) {
		SysSchedule sysSchedule = new SysSchedule();
		BeanUtils.copyProperties(sysScheduleDTO, sysSchedule);
		if(sysScheduleDao.insert(sysSchedule) > 0) {
			List<SysScheduleParticipate> participates = new ArrayList<SysScheduleParticipate>();
			// 个人待办
			if(0 == sysSchedule.getType()) {
				SysScheduleParticipate sysScheduleParticipate = new SysScheduleParticipate();
				sysScheduleParticipate.setScheduleId(sysSchedule.getId());
				sysScheduleParticipate.setUserId(currentUser.getSysTenantUserVO().getId());
				sysScheduleParticipate.setUserName(currentUser.getTrueName());
				participates.add(sysScheduleParticipate);
			} else {
				participates = sysScheduleDTO.getScheduleParticipates();
				for(SysScheduleParticipate sysScheduleParticipate : participates) {
					sysScheduleParticipate.setScheduleId(sysSchedule.getId());
				}
			}
			if(sysScheduleParticipateService.saveBatch(participates)) {
				return Result.ok();
			}
			throw new TransactionalException();
		}
		return Result.error();
	}

	@Override
	public Result<?> editSchedule(SysScheduleDTO sysScheduleDTO, SysUserVO currentUser) {
		SysSchedule sysSchedule = sysScheduleDao.selectById(sysScheduleDTO.getId());
		Integer type = sysSchedule.getType();
		BeanUtils.copyProperties(sysScheduleDTO, sysSchedule);
		if(sysScheduleDao.updateById(sysSchedule) > 0) {
			if(!type.equals(sysSchedule.getType())) {
				sysScheduleParticipateDao.delete(new QueryWrapper<SysScheduleParticipate>().eq("schedule_id", sysSchedule.getId()));
				List<SysScheduleParticipate> participates = new ArrayList<SysScheduleParticipate>();
				if(0 == type) {
					// 个人 -> 多人
					participates = sysScheduleDTO.getScheduleParticipates();
					for(SysScheduleParticipate sysScheduleParticipate : participates) {
						sysScheduleParticipate.setScheduleId(sysSchedule.getId());
					}
				} else {
					// 多人 -> 个人
					SysScheduleParticipate sysScheduleParticipate = new SysScheduleParticipate();
					sysScheduleParticipate.setScheduleId(sysSchedule.getId());
					sysScheduleParticipate.setUserId(currentUser.getSysTenantUserVO().getId());
					sysScheduleParticipate.setUserName(currentUser.getTrueName());
					participates.add(sysScheduleParticipate);
				}
				if(!sysScheduleParticipateService.saveBatch(participates)) {
					throw new TransactionalException();
				}
				
			} else {
				if(1 == type) {
					// 多人 -> 多人
					List<SysScheduleParticipate> oldParticipates = sysScheduleParticipateDao.selectList(new QueryWrapper<SysScheduleParticipate>()
							.eq("schedule_id", sysSchedule.getId()));
					List<SysScheduleParticipate> newParticipates = sysScheduleDTO.getScheduleParticipates(); 
					
					// 移除参与人：上次与当前的参与人取差集 (oldParticipates - newParticipates)
					List<Long> newUserIds = newParticipates.stream().map(SysScheduleParticipate::getUserId).collect(Collectors.toList());
					List<SysScheduleParticipate> removeParticipates = oldParticipates.stream()
							.filter(oldParticipate -> !newUserIds.contains(oldParticipate.getUserId())).collect(Collectors.toList());
					List<Long> removeParticipatesIds = removeParticipates.stream().map(SysScheduleParticipate::getId).collect(Collectors.toList());
					if(!CollectionUtils.isEmpty(removeParticipatesIds) && sysScheduleParticipateDao.deleteBatchIds(removeParticipatesIds) == 0) {
						throw new TransactionalException();
					}
					
					// 增加参与人：当前与上次的参与人取差集 (newParticipates - oldParticipates)
					List<Long> oldUserIds = oldParticipates.stream().map(SysScheduleParticipate::getUserId).collect(Collectors.toList());
					List<SysScheduleParticipate> addParticipates = newParticipates.stream()
							.filter(newParticipate -> !oldUserIds.contains(newParticipate.getUserId())).collect(Collectors.toList());
					for(SysScheduleParticipate sysScheduleParticipate : addParticipates) {
						sysScheduleParticipate.setScheduleId(sysSchedule.getId());
					}
					if(!CollectionUtils.isEmpty(addParticipates) && !sysScheduleParticipateService.saveBatch(addParticipates)) {
						throw new TransactionalException();
					}
				}
			}
			return Result.ok();
		}
		return Result.error();
	}

	@Override
	public IPage<SysScheduleVO> pageSchedule(IPage<SysScheduleVO> page, SysScheduleDTO sysScheduleDTO, SysUserVO sysUserVO) {
		return sysScheduleDao.pageSchedule(page, sysScheduleDTO, sysUserVO);
	}

	@Override
	public SysScheduleVO getDetail(Long id, SysUserVO sysUserVO) {
		return sysScheduleDao.getDetail(id, sysUserVO);
	}

	@Override
	public Result<?> finishSchedule(Long id, SysUserVO currentUser) {
		SysSchedule sysSchedule = sysScheduleDao.selectById(id);
		if(0 == sysSchedule.getType()) {
			// 个人
			sysSchedule.setScheduleStatus(1);
			if(sysScheduleDao.updateById(sysSchedule) > 0) {
				SysScheduleParticipate sysScheduleParticipate = sysScheduleParticipateDao.selectOne(new QueryWrapper<SysScheduleParticipate>()
						.eq("schedule_id", sysSchedule.getId()));
				sysScheduleParticipate.setParticipateStatus(1);
				sysScheduleParticipate.setCreatorStatus(1);
				if(sysScheduleParticipateDao.updateById(sysScheduleParticipate) == 0) {
					throw new TransactionalException();
				}
			}
		} else {
			// 多人 
			if(!sysSchedule.getCreateBy().equals(currentUser.getSysTenantUserVO().getId())) {
				// 不是创建者，修改个人日程状态
				SysScheduleParticipate sysScheduleParticipate = sysScheduleParticipateDao.selectOne(new QueryWrapper<SysScheduleParticipate>()
						.eq("schedule_id", sysSchedule.getId()).eq("user_id", currentUser.getSysTenantUserVO().getId()));
				sysScheduleParticipate.setParticipateStatus(1);
				if(sysScheduleParticipateDao.updateById(sysScheduleParticipate) == 0) {
					throw new TransactionalException();
				}
			} else {
				// 是创建者，修改日程总状态并修改所有参与者创建者状态
				sysSchedule.setScheduleStatus(1);
				if(sysScheduleDao.updateById(sysSchedule) > 0) {
					List<SysScheduleParticipate> scheduleParticipates = sysScheduleParticipateDao.selectList(new QueryWrapper<SysScheduleParticipate>()
							.eq("schedule_id", sysSchedule.getId()));
					for(SysScheduleParticipate sysScheduleParticipate : scheduleParticipates) {
						sysScheduleParticipate.setCreatorStatus(1);
					}
					
					if(!sysScheduleParticipateService.updateBatchById(scheduleParticipates)) {
						throw new TransactionalException();
					}
				}
			}
			
		}
		return Result.ok();
	}

	@Override
	public List<SysScheduleVO> listSchedule(String startDate, String endDate, SysUserVO currentUser) {
		return sysScheduleDao.listSchedule(startDate, endDate, currentUser);
	}

	@Override
	public Result<?> finishCreate(List<Long> ids, SysUserVO currentUser) {
		List<SysScheduleParticipate> scheduleParticipates = sysScheduleParticipateDao.selectBatchIds(ids);
		for(SysScheduleParticipate sysScheduleParticipate : scheduleParticipates) {
			sysScheduleParticipate.setCreatorStatus(1);
			if(sysScheduleParticipate.getUserId().equals(currentUser.getSysTenantUserVO().getId())) {
				sysScheduleParticipate.setParticipateStatus(1);
			}
		}
		return sysScheduleParticipateService.updateBatchById(scheduleParticipates) ? Result.ok() : Result.error();
	}

	@Override
	public List<String> listScheduleDate(String startDate, String endDate, SysUserVO currentUser) {
		return sysScheduleDao.listScheduleDate(startDate, endDate, currentUser);
	}

	
}